/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "dma.h"
#include "fatfs.h"
#include "sdio.h"
#include "spi.h"
#include "tim.h"
#include "usart.h"
#include "usb_device.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "LED.h"
#include "ws2812.h"
#include "EncoderPAD.h"
#include "oled_ui.h"
#include "TestUI.h"
#include "MulTask.h"
#include "usbd_Composite.h"
#include "shell_port.h"
#include "W25QXX.h"
#include "KeyValue.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
#define WS2812_PIXEL_NUM 2

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
Task idle_task;
Task breath_led_task;
Task key_task;
Task uart_task;
Task encoder_pad_task;
uint8_t ws2812_fsm = 0;
s_ws2812 ws2812;
//以下四个变量与TestUI共享
FIL g_setting_file = {0};
uint8_t g_setting_file_array[3] = {0}; 
//设置文件读出的内容，[0] 表示配置文件是否存在，[1] oled_inv; [2] volumn_mode(0表示音量模式，1表示上下曲)
char g_setting_file_buff[256] = {0};  //设置文件读出的buffer
Dict g_setting_dict; //设置文件读出的字典
uint8_t g_volumn_ctrl_state = 0; // 音量控制的状态 0 normal, 1 mute 2 plus 3 minus 
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
FRESULT fatfs_get_info( const TCHAR* drv, uint32_t *total, uint32_t *free);
void idle_cb(void * p_context);
void breath_led_cb(void * p_context);
void key_cb(void * p_context);
void uart_cb(void *p_context);
void encoder_pad_cb(void * p_context);
/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */

 int main(void)
 {
     HAL_Init();
     SystemClock_Config();
     MX_GPIO_Init();
     MX_DMA_Init();
     MX_USART1_UART_Init();
     MX_TIM3_Init();
     WS2812_Init(&ws2812,6);
     WS2812_ClearAllPixel(&ws2812);
     ws2812_Send_Data(&ws2812);
     while(1)
     {
         WS2812_SetPixel(&ws2812,0,0xF0,0x00,0x00);
         WS2812_SetPixel(&ws2812,1,0x0F,0x00,0x00);
         WS2812_SetPixel(&ws2812,2,0x00,0xF0,0x00);
         WS2812_SetPixel(&ws2812,3,0x00,0x0F,0x00);
         WS2812_SetPixel(&ws2812,4,0x00,0x00,0xF0);
         WS2812_SetPixel(&ws2812,5,0x00,0x00,0x0F);
         ws2812_Send_Data(&ws2812);
         printf("Sheep1\r\n");
         HAL_Delay(3000);
         WS2812_SetPixel(&ws2812,5,0xF0,0x00,0x00);
         WS2812_SetPixel(&ws2812,4,0x0F,0x00,0x00);
         WS2812_SetPixel(&ws2812,3,0x00,0xF0,0x00);
         WS2812_SetPixel(&ws2812,2,0x00,0x0F,0x00);
         WS2812_SetPixel(&ws2812,1,0x00,0x00,0xF0);
         WS2812_SetPixel(&ws2812,0,0x00,0x00,0x0F);
         ws2812_Send_Data(&ws2812);
         HAL_Delay(3000);
         printf("Sheep2\r\n");
     }
 }




/**
  * @brief  The application entry point.
  * @retval int
  */
//int main(void)
//{
//    /* USER CODE BEGIN 1 */
//    uint16_t w25q64_id = 0;  
//    FRESULT res = FR_OK; //文件操作返回值
//    uint32_t total_size = 0, free_size = 0; //设备容量大小
//    /* USER CODE END 1 */

//    /* MCU Configuration--------------------------------------------------------*/

//    /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
//    HAL_Init();

//    /* USER CODE BEGIN Init */

//    /* USER CODE END Init */

//    /* Configure the system clock */
//    SystemClock_Config();

//    /* USER CODE BEGIN SysInit */

//    /* USER CODE END SysInit */

//    /* Initialize all configured peripherals */
//    MX_GPIO_Init();
//    MX_DMA_Init();
//    MX_USART1_UART_Init();
//    MX_TIM3_Init();
//    MX_SDIO_SD_Init();
//    MX_SPI1_Init();
//    MX_SPI2_Init();
//    MX_TIM2_Init();
//    MX_FATFS_Init();
//    //  MX_USB_DEVICE_Init();
//    /* USER CODE BEGIN 2 */
//    w25q64_id = W25QXX_ReadID();
//    printf("W25QXX ID = %04X\r\n",w25q64_id);
//    //关闭多余的灯
//    LED_OFF(GREEN);
//    LED_OFF(BLUE);
//    //初始化ws2812灯带，并清空
//    WS2812_Init(&ws2812,WS2812_PIXEL_NUM);
//    WS2812_ClearAllPixel(&ws2812);
//    ws2812_Send_Data(&ws2812);
//    //Falsh FATFS初始化
//    res = f_mount(&USERFatFS, (const TCHAR *)"0:/", 1); //挂在外部flash到0
//    if(res == FR_OK){printf("mount Flash OK\r\n");LED_ON(BLUE);} //挂载成功，点亮蓝灯示意
//    else printf("mount Flash err = %d\r\n",res);
//    res = fatfs_get_info((const TCHAR *)"0:/",&total_size,&free_size);
//    if(res == FR_OK)printf("get Flash size OK, total=%d,free= %d\r\n",total_size,free_size);
//    else printf("get Flash size err = %d\r\n",res);
//    // //SDIO FATFS初始化
//    res = f_mount(&SDFatFS, (const TCHAR *)"1:/", 1);//挂在SD卡到1
//    if(res == FR_OK){printf("mount SD OK\r\n");LED_ON(BLUE);} //挂载成功，点亮蓝灯示意
//    else printf("mount SD err = %d\r\n",res);
//    res = fatfs_get_info((const TCHAR *)"1:/",&total_size,&free_size);
//    if(res == FR_OK)printf("get SD size OK, total=%d,free= %d\r\n",total_size,free_size);
//    else printf("get SD size err = %d\r\n",res);
//    // FIL chinese_file_test;
//    #if (TABLE_IN_FLASH!=1) //使用Flash存储utf-8到gbk2312的转换表
//        res = load_conversion_table_files(); 
//        if(res == FR_OK)printf("load conversion table files OK\r\n");
//        else printf("load conversion table files err = %d\r\n",res);
//    #endif
//    //OLED初始化HAL_Delay(1000); 
//    OLED_Init();
//    //读取配置文件更正显示方向
//    res = f_open(&g_setting_file,SETTING_DIR_PATH"/setting.txt",FA_READ);
//    if (FR_OK == res){
//        eDICT_ERR ret = eDICT_ERR_OK;
//        char temp[32] = {0};
//        UINT br;
//        ret = Dict_Init(&g_setting_dict);
//        f_read(&g_setting_file,&g_setting_file_buff,sizeof(g_setting_file_buff),&br);
//        ret = Dict_Loads(&g_setting_dict,g_setting_file_buff);
//        g_setting_file_array[0] = 1; //表示这个文件存在
//        if(ret == eDICT_ERR_OK)
//        {
//            printf("%s",g_setting_file_buff);
//            if(eDICT_ERR_OK == Dict_GetValue(&g_setting_dict,"oled_inv",temp))
//            {
//                g_setting_file_array[1] = temp[0] - '0';
//                if(0 == strcmp(temp,"1"))
//                    {OLED_DisplayTurn(1); printf("oled_inv=1");}//反转显示
//                else if(0 == strcmp(temp,"0"))
//                    {OLED_DisplayTurn(0); printf("oled_inv=0");}
//            }
//            if(eDICT_ERR_OK == Dict_GetValue(&g_setting_dict,"volumn_mode",temp))
//            {
//                g_setting_file_array[2] = temp[0] - '0';
//                if(0 == strcmp(temp,"1"))
//                    {printf("volumn_mode=1");}
//                else if(0 == strcmp(temp,"0"))
//                    {printf("volumn_mode=0");}
//            }
//        }
//        // Dict_Clears(&g_setting_dict);
//        f_close(&g_setting_file);
//    }
//    MX_USB_DEVICE_Init();
//    // encoderpad 的tim2编码器模式初始化
//    HAL_TIM_Encoder_Start(&htim2,TIM_CHANNEL_ALL);
//    // WouoUIPage的初始化，包含了oled的初始化
//    TestUI_Init();
//    User_Shell_Init(); //usb shell 初始化
//    //MulTask初始化并启用
//    MulTask_Init(&idle_task,idle_cb,NULL);
//    MulTask_TaskInit(&key_task,10,key_cb,NULL);
//    MulTask_SetTaskStartTick(&key_task,5); //将keytask的初始task设置为5，有利于错开task运行
//    MulTask_TaskInit(&uart_task,30,uart_cb,NULL);
//    MulTask_SetTaskStartTick(&key_task,17); //将keytask的初始task设置为2，有利于错开task运行
//    MulTask_TaskInit(&encoder_pad_task,100,encoder_pad_cb,NULL);
//    MulTask_TaskInit(&breath_led_task,1000,breath_led_cb,NULL);
//    /* USER CODE END 2 */

//    /* Infinite loop */
//    /* USER CODE BEGIN WHILE */
//    while (1)
//    {
//        /* USER CODE END WHILE */

//        /* USER CODE BEGIN 3 */
//        MulTask_Loop();
//    }
//  /* USER CODE END 3 */
//}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB;
  PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_PLL_DIV1_5;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */
void breath_led_cb(void * p_context)
{
    switch(ws2812_fsm)
    {
        case 0 : //红绿
            WS2812_SetPixel(&ws2812,0,0x0F,0x00,0x00);
            WS2812_SetPixel(&ws2812,1,0x00,0x0F,0x00);
            ws2812_fsm++;
            break;
        case 1 : //绿蓝
            WS2812_SetPixel(&ws2812,0,0x00,0x0F,0x00);
            WS2812_SetPixel(&ws2812,1,0x00,0x00,0x0F);
            ws2812_fsm++;
            break;
        case 2 : //蓝红
            WS2812_SetPixel(&ws2812,0,0x00,0x00,0x0F);
            WS2812_SetPixel(&ws2812,1,0x0F,0x00,0x00);
            ws2812_fsm++;
            break;
        case 3 : //清空
            WS2812_ClearAllPixel(&ws2812);
            ws2812_fsm=0;
        break;
    }
    ws2812_Send_Data(&ws2812);
    LED_TOGGLE(GREEN);
}
void idle_cb(void * p_context)
{
    //按键处理
    KeySta user_key_sta = KEY_Read(USER_KEY1);
    KeySta pad_key_sta = KEY_Read(PAD_KEY);
    switch (user_key_sta)
    {
        case KS_short_release:
            OLED_MsgQueSend(msg_return);
            break;
    
        default:break;
    }
    switch (pad_key_sta)
    {   
        case KS_short_release:
            OLED_MsgQueSend(msg_click);
            if((Page*)(&g_volumn_page) == OLED_GetCurrentPage())
            {
                if(g_setting_file_array[2] == 0)
                {//静音与否
                    USBD_CUSTOM_HID_CtrlMusicPress(eUSBHID_REPORT_Mute);
                    HAL_Delay(10);
                    USBD_CUSTOM_HID_CtrlMusicRelease();
                    if(g_volumn_ctrl_state == 0) g_volumn_ctrl_state = 1;
                    else if(g_volumn_ctrl_state != 0)g_volumn_ctrl_state = 0;
                }
                else if(g_setting_file_array[2] == 1)
                {
                    USBD_CUSTOM_HID_CtrlMusicPress(eUSBHID_REPORT_PP);
                    HAL_Delay(10);
                    USBD_CUSTOM_HID_CtrlMusicRelease();
                    if(g_volumn_ctrl_state == 0) g_volumn_ctrl_state = 1;
                    else if(g_volumn_ctrl_state != 0)g_volumn_ctrl_state = 0;
                }
            }
            break;
        case KS_long_release:
            OLED_MsgQueSend(msg_return);
            break;
        default: break;
    }
    // //WouoUI主循环
    // TestUI_Proc();
    //Shell的处理
    User_ShellTask();   
}

void key_cb(void *p_context)
{
    KEY_Scan(); //执行按键扫描
}

void uart_cb(void *p_context)
{
//   static uint8_t temp = 0;
//   if(HAL_UART_Receive_IT(&huart1,&temp,1) == HAL_OK)
//   {
//       switch (temp)
//       {
//         case 'a':
//         case 'b':
//         case 'c':
//         case 'd':
//         case 'e':
//         case 'f':
//         case 'g':
//             printf("report %d",temp-'a');
//             USBD_CUSTOM_HID_CtrlMusicPress((eUSBHID_REPORT)(temp - 'a'));
//             HAL_Delay(10);
//             USBD_CUSTOM_HID_CtrlMusicRelease();
//         break;
//       default:
//         break;
//       }
//   }
    //WouoUI主循环
    TestUI_Proc();
}


void encoder_pad_cb(void *p_context)
{
    short encoder_num = (short)__HAL_TIM_GET_COUNTER(&htim2);
    uint8_t encoder_dir = __HAL_TIM_IS_TIM_COUNTING_DOWN(&htim2);
    if(encoder_num != 0 )
    {
        printf("Dir = %d\r\n",encoder_dir);
        printf("ENcoder = %d\r\n",encoder_num);
        if(encoder_dir) // CCW
        {
            OLED_MsgQueSend(msg_down);
            if((Page*)(&g_volumn_page) == OLED_GetCurrentPage()) //当前在音量原页面的话
            {
                g_volumn_ctrl_state = 3;
                if(g_setting_file_array[2] == 0)
                {
                    USBD_CUSTOM_HID_CtrlMusicPress(eUSBHID_REPORT_VolDown);
                    HAL_Delay(10);
                    USBD_CUSTOM_HID_CtrlMusicRelease();
                }else if(g_setting_file_array[2] == 1)
                {
                    USBD_CUSTOM_HID_CtrlMusicPress(eUSBHID_REPORT_Pre);
                    HAL_Delay(10);
                    USBD_CUSTOM_HID_CtrlMusicRelease();
                }
            }
        }
        else //CW
        {
            OLED_MsgQueSend(msg_up);
            if((Page*)(&g_volumn_page) == OLED_GetCurrentPage())//当前在音量原页面的话
            {
                g_volumn_ctrl_state = 2;
                if(g_setting_file_array[2] == 0)
                {// volume increase
                    USBD_CUSTOM_HID_CtrlMusicPress(eUSBHID_REPORT_VolUp);
                    HAL_Delay(10);
                    USBD_CUSTOM_HID_CtrlMusicRelease();
                }
                else if(g_setting_file_array[2] == 1)
                {
                    USBD_CUSTOM_HID_CtrlMusicPress(eUSBHID_REPORT_Next);
                    HAL_Delay(10);
                    USBD_CUSTOM_HID_CtrlMusicRelease();
                }
            }
        }
        __HAL_TIM_SET_COUNTER(&htim2,0);
      }
}

FRESULT fatfs_get_info( const TCHAR* drv, uint32_t *total, uint32_t *free)
{
    FATFS *pfs;
    uint32_t fre_clust=0, fre_sect=0, tot_sect=0;
    
    FRESULT res = f_getfree((const TCHAR*)drv, (DWORD *)&fre_clust, &pfs);
    if(res==0) {
        tot_sect = (pfs->n_fatent - 2) * pfs->csize;    // total sectors
        fre_sect = fre_clust * pfs->csize;            // free sectors
            
#if _MAX_SS != 512                                // 
        tot_sect *= pfs->ssize / 512;
        fre_sect *= pfs->ssize / 512;
#endif      
        *total = tot_sect >> 1;    // KB
        *free = fre_sect >> 1;     // KB 
    }
    return res;
}

uint8_t ws2812_SetPixel_CMD(uint8_t pixel_num, uint8_t r, uint8_t g, uint8_t b)
{
    if(pixel_num < WS2812_PIXEL_NUM)
    {
        WS2812_SetPixel(&ws2812, pixel_num,r , g , b);
        return 0;
    }
    else return 1;
}
uint8_t ws2812_Send_Data_CMD(void)
{
    ws2812_Send_Data(&ws2812);
    return 0;
}

uint8_t ws2812_ClearAllPixel_CMD(void)
{
    WS2812_ClearAllPixel(&ws2812);
    return 0;
}

SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC), ws_set_pixel, ws2812_SetPixel_CMD, <ws_set_pixel num r g b>);
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC), ws_clear_pixel, ws2812_ClearAllPixel_CMD, <ws_clear_pixel>);
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC), ws_send, ws2812_Send_Data_CMD, <ws_send>);
SHELL_EXPORT_VAR(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_VAR_CHAR), ws_fsm, &ws2812_fsm, <ws2812_fsm>);
/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
